package com.dongdongshop.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.dongdongshop.constant.HttpResultEnum;
import com.dongdongshop.data.DataResult;
import com.dongdongshop.pojo.cart.Cart;
import com.dongdongshop.pojo.item.TbItem;
import com.dongdongshop.pojo.user.TbUser;
import com.dongdongshop.util.CookieUtils;
import com.dongdongshop.util.HttpClientUtil;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.Subject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 购物车
 * @Author Eayon
 * @Date 2020/4/4 9:41
 */
@Controller
@RequestMapping("cart")
public class CartController {

    private static final Logger log = LoggerFactory.getLogger(CartController.class);

    private static final String CART_URL = "http://localhost:8765/cartservice/cart/";

    private static final String ITEM_URL = "http://localhost:8765/itemservice/item/";

    /**
     * 判断用户是否登录，登录就从redis中获取，未登录就从cookie中获取购物车
     * Cart代表一个商家购物车   List<Cart>那就代表整个购物车页面了 可理解为一个大的购物车
     * @param request
     * @return
     */
    @RequestMapping("getCart")
    @ResponseBody
    public List<Cart> getCart(HttpServletRequest request, HttpServletResponse response) throws IOException {
        //从Shiro中获取登录的用户
        Subject subject = SecurityUtils.getSubject();
        TbUser user = (TbUser)subject.getPrincipal();
        //一、判断用户是否登录
        if(user == null){
            log.info("用户未登录，从cookie中获取购物车");
            //用户未登录，从cookie中获取该用户购物车
            // 1、使用cookieUtil从cookie中获取该用户购物车数据(List<Cart>大购物车)
            String cartList = CookieUtils.getCookieValue(request, "cartList", "UTF-8");
            // 2、判断购物车是否为空，如果为空赋值空数组（可能该用户没有在cookie中存储过商品，如果为null的话后面转换错误，所以赋值空数组）
            if(StringUtils.isBlank(cartList)){
                cartList = "[]";
            }
            // 3、将cartList解析成实体进行返回；
            List<Cart> cartsByCookie = JSONObject.parseArray(cartList, Cart.class);
            log.info("从cookie中获取到用户购物车数据：{}", JSONObject.toJSONString(cartsByCookie));
            return cartsByCookie;
        }else { //二、如果用户登录了
            log.info("用户：{} 已登录，从缓存中获取购物车",user.getUsername());
            // 1、从redis中获取该用户的购物车
            Map<String,String> params = new HashMap<>();
            String dataResultStr = HttpClientUtil.doGet(CART_URL + user.getUsername(), params);
            DataResult dataResult = JSONObject.parseObject(dataResultStr, DataResult.class);
            Object data = dataResult.getData();
            List<Cart> cartsByCache = JSONObject.parseArray(JSONObject.toJSONString(data), Cart.class);
            log.info("从缓存中获取该用户购物车数据：{}",JSONObject.toJSONString(cartsByCache));
            //2、再取出该用户cookie中的购物车
            String cartList = CookieUtils.getCookieValue(request, "cartList", "UTF-8");
            List<Cart> cartsByCookie = JSONObject.parseArray(cartList, Cart.class);
            log.info("从cookie中获该用户取购物车数据：{}",JSONObject.toJSONString(cartsByCookie));
            //3、判断cookie中是否有数据，有数据在进行缓存和cookie购物车的合并，缓存没有就没必要合并
            if(cartsByCookie != null && cartsByCookie.size() > 0){
                log.info("该用户的cookie中购物车有数据，开始进行缓存和cookie购物车合并.....");
                //将cookie购物车的数据和redis中购物车的数据进行合并，返回合并完成的购物车
                Map<String,String> params2 = new HashMap<>();
                params2.put("carsByCache",JSONObject.toJSONString(cartsByCache));
                params2.put("carsByCookie",JSONObject.toJSONString(cartsByCookie));
                String dataResultStr2 = HttpClientUtil.doGet(CART_URL + "mergeCarList", params2);
                DataResult dataResult2 = JSONObject.parseObject(dataResultStr2, dataResult.getClass());
                Object data2 = dataResult2.getData();
                List<Cart> mergeCarts = JSONObject.parseArray(JSON.toJSONString(data2), Cart.class);
                //合并完成后清除cookie中的数据
                CookieUtils.deleteCookie(request,response,"cartList");
                //将合并后的数据保存到redis中
                Map<String,String> params3 = new HashMap<>();
                params3.put("cartList",JSONObject.toJSONString(mergeCarts));
                params3.put("username",user.getUsername());
                String dataResultStr3 = HttpClientUtil.doPost(CART_URL + "save", params3);
                //返回合并后的
                return mergeCarts;
            }
            //cookie没数据就直接返回redis的购物车
            return cartsByCache;
        }
    }

    /**
     * 点击商品添加到购物车(添加到cookie或者redis)
     * @param request
     * @param response
     * @param itemId    被点击商品的id
     * @param num       该商品的数量
     */
    @RequestMapping("addGoodsToCartList")
    public String addGoodsToCartList(HttpServletRequest request, HttpServletResponse response, Long itemId, Integer num, Model model){
        try {
            log.info("进入添加商品到购物车方法，商品ID：{}，商品数量：{}",itemId,num);
            //cookie不能直接往里面增加商品，会把原来的给覆盖掉
            //1、调用封装方法去查询cookie或者redis中的购物车。集合中是每个商家购物车
            List<Cart> cartList = getCart(request,response);
            // 2、调用购物车服务   往大购物车中添加用户添加的商品信息
            //将cookie中原先的数据也发送过去，因为如果直接往cookie中增加会覆盖原来的，所以需要让购物车服务将原来的和新的进行组装然后返回
            //所以返回回来的数据可以直接是新的和旧的数据组装到一起的list，所以返回值可以直接覆盖原先的List<Cart> cartList集合
            log.info("执行调用购物车服务【添加商品到购物车集合并重新组装】.....");
            Map<String,String> params = new HashMap<>();
            params.put("cartList",JSONObject.toJSONString(cartList));
            params.put("itemId",itemId.toString());
            params.put("num",num.toString());
            String dataResultStr = HttpClientUtil.doGet(CART_URL +"addGoodsToCartList", params);
            log.info("添加商品到购物车集合并重新组装结果：{}",dataResultStr);
            DataResult dataResult = JSONObject.parseObject(dataResultStr, DataResult.class);
            Object data = dataResult.getData();
            cartList = JSONObject.parseArray(JSONObject.toJSONString(data), Cart.class);
            //从shiro中取出登录用户
            Subject subject = SecurityUtils.getSubject();
            TbUser user = (TbUser)subject.getPrincipal();
            //如果用户没登陆存入cookie
            if(user==null){
                //3、将大购物车对象集合写入cookie   cookieMaxage：该参数为cookie的存活时间，单位分钟，60分钟*24*7=7天
                CookieUtils.setCookie(request,response,"cartList", JSONObject.toJSONString(cartList),60*24*7,"UTF-8");
                log.info("购物车数据成功存入cookie..");
            }else{  //登录就保存redis
                Map<String,String> params3 = new HashMap<>();
                params3.put("cartList",JSONObject.toJSONString(cartList));
                String username = user.getUsername();
                params3.put("username",username);
                String dataResultStr2 = HttpClientUtil.doPost(CART_URL + "save", params3);
            }
            //根据itemId查询该商品信息
            Map<String,String> params3 = new HashMap<>();
            String dataResultStr3 = HttpClientUtil.doGet(ITEM_URL + itemId, params3);
            DataResult dataResult3 = JSONObject.parseObject(dataResultStr3, DataResult.class);
            Object data3 = dataResult3.getData();
            TbItem item = JSONObject.parseObject(JSONObject.toJSONString(data3), TbItem.class);
            model.addAttribute("item",item);
        }catch (Exception e){
            log.error("添加商品到购物车异常",e);
            //return new DataResult(HttpResultEnum.ERROR.getCode(),HttpResultEnum.ERROR.getMessage());
        }
        //跳转购物车页面
        return "cart/successCart";
    }


    /**
     * 获取该用户的购物车并返回购物车页面
     */
    @RequestMapping("toCartList")
    public String toCartList(HttpServletRequest request,Model model){
        //从shiro中取出登录用户
        Subject subject = SecurityUtils.getSubject();
        TbUser user = (TbUser)subject.getPrincipal();
        if(user==null){
            String cartList = CookieUtils.getCookieValue(request, "cartList", "UTF-8");
            List<Cart> cartsCookie = JSONObject.parseArray(cartList, Cart.class);
            model.addAttribute("cartList",cartsCookie);
        }else{
            //登录就从redis中取出购物车
            Map<String,String> params = new HashMap<>();
            String dataResultStr = HttpClientUtil.doGet(CART_URL + user.getUsername(), params);
            DataResult dataResult = JSONObject.parseObject(dataResultStr, DataResult.class);
            Object data = dataResult.getData();
            List<Cart> cartsRedis = JSONObject.parseArray(JSONObject.toJSONString(data), Cart.class);
            model.addAttribute("cartList",cartsRedis);
        }
        return "cart/cartList";
    }

}
